/*
 * Copyright 2008-2010 GP Software
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 * XlsReader.java | Created on Sep 29, 2010
 */
package org.gpsoftware.xlsMerge.fileReader;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.gpsoftware.xlsMerge.ReadException;
import org.gpsoftware.xlsMerge.Row;
import org.gpsoftware.xlsMerge.XlsRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

/**
 * The MS Excel file reader
 *
 * @author Paul Augustine C. Mendoza
 */
class XlsFileReader implements FileReader<HSSFRow> {

    private static final int DEFAULT_LOCALE_INDEX = 1;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public Set<Row<HSSFRow>> read(File inputFile) throws ReadException {
        if (!inputFileExists(inputFile)) {
            throw new IllegalArgumentException("Input file does not exist.");
        }
        logger.info("Reading " + inputFile.getPath());
        Set<Row<HSSFRow>> rows = null;
        InputStream xlsFile = null;
        try {
            xlsFile = new FileInputStream(inputFile);
            HSSFWorkbook workbook = new HSSFWorkbook(xlsFile);
            rows = parseWorkbook(workbook);
        } catch (FileNotFoundException fnfe) {
            throw new ReadException(fnfe, inputFile);
        } catch (IOException ioe) {
            throw new ReadException(ioe, inputFile);
        } catch (Exception e) {
            throw new ReadException(e, inputFile);
        } finally {
            if (xlsFile != null) {
                try {
                    xlsFile.close();
                } catch (IOException ioe) {
                    logger.error(ioe.getMessage(), ioe);
                }
            }
        }
        return rows;
    }

    private boolean inputFileExists(File inputFile) {
        return (inputFile != null) && (inputFile.exists());
    }

    private Set<Row<HSSFRow>> parseWorkbook(HSSFWorkbook workbook) {
        Set<Row<HSSFRow>> rows = new TreeSet<Row<HSSFRow>>();
        HSSFSheet sheet;
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            sheet = workbook.getSheetAt(i);
            logger.info("Reading sheet " + sheet.getSheetName() + "...");
            rows.addAll(parseSheet(sheet));
        }
        return rows;
    }

    private Set<Row<HSSFRow>> parseSheet(HSSFSheet sheet) {
        Set<Row<HSSFRow>> rows = new TreeSet<Row<HSSFRow>>();
        Iterator iterator = sheet.rowIterator();
        HSSFRow row;
        while (iterator.hasNext()) {
            row = (HSSFRow) iterator.next();
            if (!isBlank(row)) {
                rows.add(new XlsRow(row));
            }
        }
        return rows;
    }

    private boolean isBlank(HSSFRow row) {
        HSSFCell cell = (row.getCell(DEFAULT_LOCALE_INDEX) == null) ? row
                .createCell(DEFAULT_LOCALE_INDEX, Cell.CELL_TYPE_BLANK) : row
                .getCell(DEFAULT_LOCALE_INDEX);
        return (cell.getCellType() == Cell.CELL_TYPE_BLANK);
    }

}
